// 深拷贝
export default (obj) => {
    let cache = new WeakMap();
    function innerDeepClone(obj) {
        // 如果是基础类型，直接返回
        // 这里需要做一次null判断，因为typeof null是object。
        // 最终筛选的应该是，typeof不是object，但同时又不是null的才是基础类型。
        if (typeof obj !== 'object' || !obj) return obj;
        // 之后每建立一次新的tmp都需要往cache存储记录
        // 如果这个obj是已经处理过的，就直接返回，就不会因为闭环调用而无限堆栈
        if (cache.has(obj)) return cache.get(obj)

        // 新建一个变量用于存储当前处理的obj
        let tmp;
        // 处理非简单对象和数组
        if (obj instanceof Map) {
            tmp = new Map();
            cache.set(obj, tmp);
            // Map使用set方法插入
            obj.forEach((val, key) => {
                tmp.set(innerDeepClone(key), innerDeepClone(val));
            })
        } else if (obj instanceof Set) {
            tmp = new Set();
            cache.set(obj, tmp);
            // Set使用add方法插入
            obj.forEach(val => {
                tmp.add(innerDeepClone(val))
            })
        } else if (obj instanceof Date || obj instanceof RegExp) {
            // 不需要做额外处理，仅仅是tmp = new obj.constructor(obj);
            tmp = new obj.constructor(obj);
            cache.set(obj, tmp);
        } else {
            // 判断为对象或者数组
            tmp = new obj.constructor();
            cache.set(obj, tmp);
            for (let key in obj) {
                tmp[key] = innerDeepClone(obj[key]);
            }
        }
        return tmp
    }
    return innerDeepClone(obj)
}